// closures
//   anonymous functions can inherit variables from the scope they were created in
//   should list all variables explicitly that are inherited

my_int := 1
my_closure := fn [my_int] () {
	println(my_int)
}
my_closure() // prints 1

// inherited variables are copied when the anonymous function is created
mut i := 1
func := fn [i] () int {
	return i
}
println(func() == 1) // true
i = 123
println(func() == 1) // still true

// the variable can be modified inside the anonymous function
// the change won't be reflected outside, but will be in the later funcion calls
// fn new_counter fn () int {
new_counter := fn () fn () int {
	mut i := 0
	return fn [mut i] () int {
		i++
		return i
	}
}
c := new_counter()
println(c()) // 1
println(c()) // 2
println(c()) // 3

// use a reference to let the value modified outside the function
// make sure the reference is always valid
mut i2 := 0
mut ref := &i2
print_counter := fn [ref] () {
	println(*ref)
}

print_counter() // 0
i2 = 10
print_counter() // 10
